﻿using System;
using System.Collections.Generic;
using System.Threading;

namespace DotNetRepository.Tools
{
    public class ValueLock<TValueType> where TValueType : struct
    {
        private readonly HashSet<TValueType> _lockedValues = new HashSet<TValueType>();
        public ValueLocker Lock(TValueType value)
        {
            while (true)
            {
                while (true)
                {
                    lock (_lockedValues)
                        if (!_lockedValues.Contains(value)) break;
                    Thread.Sleep(1);
                }

                lock (_lockedValues)
                {
                    if (_lockedValues.Contains(value)) continue;

                    _lockedValues.Add(value);
                    return new ValueLocker(value,this);
                }
            }
        }

        public bool IsLocked(TValueType value)
        {
            lock (_lockedValues)
                return _lockedValues.Contains(value);
        }

        public void UnLock(TValueType value)
        {
            lock (_lockedValues)
                _lockedValues.Remove(value);
        }

        public class ValueLocker : IDisposable
        {
            private bool _disposed;
            private readonly TValueType _value;
            private readonly ValueLock<TValueType> _valueLock;

            internal ValueLocker(TValueType value, ValueLock<TValueType> valueLock)
            {
                _value = value;
                _valueLock = valueLock;
            }

            public void Dispose()
            {
                if (_disposed) return;
                _disposed = true;
                _valueLock.UnLock(_value);
            }
        }
    }

    
    
}
